﻿using System;
using System.Collections.Generic;

using Exif.Interfaces;
using System.ComponentModel;

using Exif.Jpeg.Segments;

namespace Exif.Tiff
{
	///<summary>
	///Базовый класс для реализации директорий файла изображения (Image File Directory, IFD)
	///</summary>
	//[TypeDescriptionProvider(typeof(ExpandableTDP))]
	[TypeConverter(typeof(ExpandableObjectConverter))]
	[ReadOnly(true)]
	public class IfdBase
	{
		#region Частные поля класса

		private Dictionary<UInt16, TagEntry> _entryMap;

		#endregion

		#region Конструкторы

		/////<summary>
		/////Конструктор
		/////</summary>
		/////<param name="parent"></param>
		/////<param name="initialize"><c>true</c> - инициализировать директорию сразу, иначе <c>false</c></param>
		//public IfdBase(TiffInfo parent, bool initialize)
		//{
		//    Parent = parent;
		//    if(initialize)
		//    {
		//        this._entryMap = new Dictionary<ushort, TagEntry>();
		//    }
		//}

		///<summary>
		///Конструктор
		///</summary>
		///<param name="parent"></param>
		///<param name="directoryCapacity">Ожидаемое количество полей в директории; директория будет инициализирована</param>
		public IfdBase(TiffInfo parent, int directoryCapacity)
		{
			Parent = parent;
			this._entryMap = new Dictionary<ushort, TagEntry>(directoryCapacity);
		}

		/////<summary>
		/////Конструктор неинициализированной директории
		/////</summary>
		/////<param name="parent"></param>
		//public IfdBase(TiffInfo parent)
		//    : this(parent, false)
		//{
			
		//}

		#endregion

		#region Свойства класса

		///<summary>
		///Возвращает число полей
		///</summary>
		public int Count
		{
			get
			{
				return this._entryMap.Count;
			}
		}

		/////<summary>
		/////Определяет, была ли директория инициализирована
		/////</summary>
		//public bool IsInitialized
		//{
		//    get { return this._entryMap != null; }
		//}

		public TiffInfo Parent { get; private set; }

		public UInt32 NexfIfdOffset { get; private set; }

		///<summary>
		///Возвращает тег по его коду, либо <c>null</c>, если такового тега в директории не найдено
		///</summary>
		///<param name="tagCode">Код тега</param>
		public TagEntry this[UInt16 tagCode]
		{
			get
			{
				TagEntry entry;
				this._entryMap.TryGetValue(tagCode, out entry);
				return entry;
			}
			set
			{
				if (this._entryMap.ContainsKey(tagCode))
				{
					this._entryMap[tagCode] = value;
				}
				else
				{
					this._entryMap.Add(tagCode, value);
				}
			}
		}

		#endregion

		#region Методы класса

		///<summary>
		///Считывает и инициализирует IFD
		///</summary>
		///<param name="reader"></param>
		public void Read(IImageReader reader)
		{
			var count = reader.ReadUInt16();

			//this._entryMap = new Dictionary<ushort, TagEntry>(count);

			while(count-- > 0)
			{
				var entry = new TagEntry(this);
				
				entry.TagID = reader.ReadUInt16();
				entry.Type = reader.ReadUInt16();
				entry.Count = reader.ReadUInt32();
				entry.ValueOffset = reader.ReadUInt32();

				entry.ReadData(reader);

				_entryMap.Add(entry.TagID, entry);
			}

			NexfIfdOffset = reader.ReadUInt32();
		}

		///<summary>
		///Считывает и инициализирует IFD
		///</summary>
		///<param name="reader">Ридер</param>
		///<param name="offset">Смещение от начала</param>
		public void Read(IImageReader reader, long offset)
		{
			reader.PushPosition(offset);
			this.Read(reader);
			reader.PopPosition();
		}

		#endregion
	}
}